package com.tangyuan.video.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.common.payment.AliPayImpl;
import com.tangyuan.common.payment.WxPayImpl;
import com.tangyuan.common.result.Result;
import com.tangyuan.common.result.ResultCodeEnum;
import com.tangyuan.common.util.DateUtil;
import com.tangyuan.dto.VideoHotDto;
import com.tangyuan.feignapis.user.IUserBalanceFeignClient;
import com.tangyuan.feignapis.user.IUserFeignClient;
import com.tangyuan.model.*;
import com.tangyuan.result.oConvertUtils;
import com.tangyuan.video.mapper.VideoHotMapper;
import com.tangyuan.video.service.*;
import com.tangyuan.vo.UserHotNum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Description: video_hot
 * @Author: jeecg-boot
 * @Date: 2024-03-12
 * @Version: V1.0
 */
@Service
@Slf4j
public class VideoHotServiceImpl extends ServiceImpl<VideoHotMapper, VideoHot> implements IVideoHotService {

    @Autowired
    VideoHotMapper videoHotMapper;
    @Autowired
    private WxPayImpl wxPayService;
    @Autowired
    private VideoThumpService videoThumpService;
    @Autowired
    private VideoService videoService;
    @Autowired
    private IVideoCommentSystemService videoCommentSystemService;
    @Autowired
    private VideoCommentService videoCommentService;

    @Autowired
    private IUserFeignClient userFeignClient;
    @Autowired
    private IUserBalanceFeignClient userBalanceFeignClient;


    public VideoHot addVideoHot(VideoHotDto videoHotDto,String orderNo) {
        VideoHot videoHot = new VideoHot();
        BeanUtils.copyProperties(videoHotDto, videoHot);
        //持续时间
        Integer time = videoHot.getTime();
        //生成订单编号
        //生成日期 起止日期
        LocalDateTime nowTime = LocalDateTime.now();
        if (videoHotDto.getHotType()==2){
            LocalDateTime endTime = nowTime.plusHours(time);
            Date endDate = DateUtil.changeLocalDateTimeToDate(endTime);
            videoHot.setEndTime(endDate);
        }
        videoHot.setOrderNo(orderNo);
        Date nowDate = DateUtil.changeLocalDateTimeToDate(LocalDateTime.now());
        videoHot.setStartTime(nowDate);
        videoHot.setCreateTime(DateUtil.changeLocalDateTimeToDate(LocalDateTime.now()));
        videoHotMapper.insert(videoHot);
        return videoHot;
    }

    @Transactional
    @Override
    public Result topHot(VideoHotDto videoHotDto) {
        String orderNo ="RM"+oConvertUtils.orderNo();
        VideoHot videoHot = addVideoHot(videoHotDto,orderNo);
        Integer type = videoHotDto.getType();
        if (type==3){
            Integer num = videoHotDto.getTypeNum();
            BigDecimal trueMoney = videoHotMapper.getTruePrice(num);
            if (trueMoney.compareTo(videoHotDto.getPayNum())!=0){
                return Result.build(null, ResultCodeEnum.INCORRECT_PAYMENT_AMOUNT);
            }
        }
        if (type==2){
            Integer num = videoHotDto.getTypeNum();
            BigDecimal trueMonry = videoHotMapper.getTruePriceline(num);
            if (trueMonry.compareTo(videoHotDto.getPayNum())!=0){
                return Result.build(null, ResultCodeEnum.INCORRECT_PAYMENT_AMOUNT);
            }
        }
        if (type==1){
            Integer time = videoHotDto.getTime();
            BigDecimal trueMonry = videoHotMapper.getTruePriceByTime(time);
            if (trueMonry.compareTo(videoHotDto.getPayNum())!=0){
                return Result.build(null, ResultCodeEnum.INCORRECT_PAYMENT_AMOUNT);
            }
        }

        Orders orders = new Orders();
        orders.setOrderNo(orderNo);
        orders.setPayType(videoHotDto.getPayType());
        orders.setPayBalance(videoHotDto.getPayNum());
        orders.setShopName("上热门");
        if (videoHotDto.getPayType() == 1) {
            // 调取微信支付
            return wxPayService.wxPay(orders);
        } else if (videoHotDto.getPayType() == 2) {
            // 调取支付宝支付
            return AliPayImpl.pay(orders);
        } else if (videoHotDto.getPayType() == 3) {
            return balancePay(orders, videoHot, videoHotDto);
        } else {
            return Result.errorMoney("支付方式不正确！");
        }
    }

    private Result balancePay(Orders orders, VideoHot videoHot, VideoHotDto videoHotDto) {

        UserBalance balance = userBalanceFeignClient.getUserBalance(videoHot.getUserId());
        User user = userFeignClient.getUserById(videoHotDto.getUserId());
        if (balance == null){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.build(null,ResultCodeEnum.ACCOUNT_LESS);
        }

        if (balance.getBalance().compareTo(orders.getPayBalance()) < 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.build(null,ResultCodeEnum.ACCOUNT_LESS);
        }
        UserBalance userBalance = new UserBalance();
        userBalance.setUserId(user.getId());
        userBalance.setType(2);
        userBalance.setTransactionId("RM" + oConvertUtils.orderNo());
        userBalance.setOrderNo(orders.getOrderNo());
        userBalance.setUpBalance(orders.getPayBalance());
        userBalance.setBalance(balance.getBalance().subtract(orders.getPayBalance()));
        userBalance.setCreateTime(new Date());
        userBalanceFeignClient.saveUserBalance(userBalance);
        videoHot.setIsPaid(1);
        this.updateById(videoHot);
        return Result.ok("上热门成功！");
    }


    @Override
    public Result<Object> robotHotLike(String params) {
        // 默认执行次数
        int count = 1;
        if (!params.isEmpty()) {
            try {
                // 传入的执行次数
                count = Integer.parseInt(params);
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            }
        }
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            List<User> userList = userFeignClient.getUserListByLastSql("limit 10");

            for (User user : userList) {
                // 找10个随机热门视频
                QueryWrapper<VideoHot> hotWrapper = new QueryWrapper<>();
                hotWrapper.eq("is_paid", 1);
                hotWrapper.eq("is_cease", 0);
                hotWrapper.orderBy(true, true, "RAND()");
                hotWrapper.last("limit 10");
                List<VideoHot> hotList = this.list(hotWrapper);

                try {
                    // 随机停1-3秒
                    int randomNumber = random.nextInt(3) + 1;
                    TimeUnit.SECONDS.sleep(randomNumber);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                for (VideoHot item : hotList) {
                    item.setUpdateTime(new Date());
                    int randomNumber = random.nextInt(1000);
                    // 1-小时 2-播放 3-点赞
                    // if (item.getType() == 3) {
                    //     // 购买点赞数 + 随机值 < 推广的点赞数   关闭订单
                    //     if ((item.getTypeNum() + randomNumber) < item.getThumpedNum()) {
                    //         item.setIsCease(1);
                    //         this.updateById(item);
                    //         break;
                    //     }
                    // }
                    // 购买的浏览量 + 随机数 < 推广的浏览量 关闭订单
                    if ((item.getTypeNum() + randomNumber) < item.getPalyedNum()) {
                        item.setIsCease(1);
                        this.updateById(item);
                        break;
                    }
                    // 查出上热门的视频
                    Video video = videoService.getById(item.getVideoId());
                    if (video == null) {
                        log.error(item.getVideoId() + " 为空！");
                        break;
                    }
                    // 购买点赞量7分之一的概率进行点赞，购买浏览量14分之一的概率点赞
                    if (item.getType() == 3 && randomNumber % 7 == 0) {
                        VideoThump thump = new VideoThump();
                        thump.setVideoId(item.getVideoId());
                        thump.setUserId(user.getId());
                        thump.setIsRobot(1);
                        thump.setCreateTime(new Date());
                        videoThumpService.save(thump);
                        video.setThumpUpNum(video.getThumpUpNum() + 1);
                        item.setThumpedNum(item.getThumpedNum() + 1);
                    } else if (randomNumber % 14 == 0) {
                        VideoThump thump = new VideoThump();
                        thump.setVideoId(item.getVideoId());
                        thump.setUserId(user.getId());
                        thump.setIsRobot(1);
                        thump.setCreateTime(new Date());
                        videoThumpService.save(thump);
                        video.setThumpUpNum(video.getThumpUpNum() + 1);
                        item.setThumpedNum(item.getThumpedNum() + 1);
                    }
                    // 浏览量增加
                    item.setPalyedNum(item.getPalyedNum() + 1);
                    this.updateById(item);
                    video.setReadNum(video.getReadNum() + 1);
                    videoService.updateById(video);
                }
            }
        }
        return Result.ok();
    }

    @Override
    public Result<Object> robotComment(String params) {
        int count = 1;
        if (!params.isEmpty()) {
            try {
                count = Integer.parseInt(params);
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            }
        }
        Random random = new Random();
        int userNum = random.nextInt(20) + 5;
        List<User> userList = userFeignClient.getUserListByLastSql("limit " + userNum);
        for (int i = 0; i < count; i++) {
            for (User user : userList) {
                QueryWrapper<Video> query = new QueryWrapper<>();
                query.eq("upload_type", 1);
                query.eq("status", 1);
                query.eq("is_deleted", 0);
                query.orderBy(true, true, "RAND()");
                int videoNum = random.nextInt(20) + 5;
                query.last("limit " + videoNum);
                List<Video> videos = videoService.list(query);
                for (Video video : videos) {
                    List<VideoComment> commentList = videoCommentService.list(new LambdaQueryWrapper<VideoComment>()
                            .eq(VideoComment::getUserId, user.getId()).eq(VideoComment::getVideoId, video.getId()));
                    if (!commentList.isEmpty()) {
                        log.info("当前用户已评论！");
                        continue;
                    }
                    QueryWrapper<VideoCommentSystem> commentWrapper = new QueryWrapper<>();
                    commentWrapper.orderBy(true, true, "RAND()");
                    commentWrapper.last("limit 1");
                    VideoCommentSystem commentSystem = videoCommentSystemService.getOne(commentWrapper);
                    commentList = videoCommentService.list(new LambdaQueryWrapper<VideoComment>()
                            .like(VideoComment::getContent, commentSystem.getContent()).eq(VideoComment::getVideoId, video.getId()));
                    if (!commentList.isEmpty()) {
                        log.info("当前评论已存在！");
                        continue;
                    }
                    VideoComment videoComment = new VideoComment();
                    videoComment.setCreateTime(new Date());
                    videoComment.setCreateBy((System.currentTimeMillis() / 1000) + "");
                    videoComment.setContent(commentSystem.getContent());
                    videoComment.setVideoId(video.getId());
                    videoComment.setUserIcon(user.getHeadImage());
                    videoComment.setArea(user.getProvince());
                    videoComment.setUserId(user.getId());
                    videoComment.setUserName(user.getName());
                    videoComment.setType(1);
                    videoComment.setParentId(0L);
                    videoComment.setThumpUpNum(0);
                    videoCommentService.save(videoComment);
                }
            }
        }
        return Result.ok();
    }

    @Override
    public void determineHot(Long videoId) {
        VideoHot videoHot = this.getOne(new LambdaQueryWrapper<VideoHot>()
                .ge(VideoHot::getEndTime, new Date())
                .or().isNull(VideoHot::getEndTime)
                .eq(VideoHot::getIsPaid, 1)
                .eq(VideoHot::getIsCease, 0)
                .eq(VideoHot::getVideoId, videoId)
                .orderByAsc(VideoHot::getId).last("limit 1"));
        if (videoHot != null) {
            Random random = new Random();
            int randomNumber = random.nextInt(100) + 5;
            videoHot.setPalyedNum(videoHot.getPalyedNum() + 1);
            if (videoHot.getTypeNum() != null) {
                if ((videoHot.getTypeNum() + randomNumber) < videoHot.getThumpedNum()) {
                    videoHot.setIsCease(1);
                }
            }
            this.updateById(videoHot);
        }
    }


    /**
     * @param videoId
     */
    @Override
    public void browseHot(Long videoId) {
        VideoHot videoHot = this.getOne(new LambdaQueryWrapper<VideoHot>()
                .ge(VideoHot::getEndTime, new Date())
                .or().isNull(VideoHot::getEndTime)
                .eq(VideoHot::getIsPaid, 1)
                .eq(VideoHot::getIsCease, 0)
                .eq(VideoHot::getVideoId, videoId)
                .orderByAsc(VideoHot::getId).last("limit 1"));
        if (videoHot != null) {
            Random random = new Random();
            int randomNumber = random.nextInt(100) + 5;
            videoHot.setPalyedNum(videoHot.getPalyedNum() + 1);
            if (videoHot.getHotType() == 1) {
                if ((videoHot.getTypeNum() + randomNumber) < videoHot.getPalyedNum()) {
                    videoHot.setIsCease(1);
                }
            }
            this.updateById(videoHot);
        }
        Video video = videoService.getById(videoId);
        if (video != null) {
            video.setReadNum(video.getReadNum() + 1);
            videoService.updateById(video);
        }
    }

    @Override
    public Result getTime() {
        List<UserHotNum> list = videoHotMapper.getTime();
        return Result.ok(list);
    }

    @Override
    public Result getPrice(Integer type, Integer num) {
        return Result.ok(videoHotMapper.getPrice(type, num));
    }

    @Override
    public VideoHot selectByOrderNo(String outTradeNo) {
        return videoHotMapper.selectByOrderNo(outTradeNo);
    }
}
